import 'dart:async';
import 'dart:io';

import 'package:bloc/bloc.dart';
import 'package:dingtalk/core/common/chat_contants.dart';
import 'package:dingtalk/core/common/message_type.dart';
import 'package:dingtalk/core/events/connect_event.dart';
import 'package:dingtalk/core/events/message_event.dart';
import 'package:dingtalk/core/model/chat_model.dart';
import 'package:dingtalk/core/model/message_template.dart';
import 'package:dingtalk/core/utils/event_bus_util.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;
import 'package:socket_io_client/socket_io_client.dart';

part 'chat_event.dart';

part 'chat_state.dart';

const String _SOCKET_IOS_URL = "http://127.0.0.1:9000";
const String _SOCKET_ANDROID_URL = "http://10.0.2.2:9000";

class THChatBloc extends Bloc<THChatEvent, THChatState> {
  IO.Socket _socketChannel;

  THChatBloc() : super(THChatInitialState());

  DateTime _currentTime = DateTime.now();

  // current login user info
  String accessToken = 'f6a28737-5108-4dcc-83de-30b0847d8a12';
  String currentUserId = '785919644501544960';
  String currentUserName = '江景';

  @override
  Stream<THChatState> mapEventToState(
    THChatEvent event,
  ) async* {
    int isSend = 1;
    if (event is THChatInitEvent) {
      if (null == _socketChannel) _initChat(currentUserId, accessToken);
    } else if (event is THChatMessageListEvent) {
      List<THChatModel> list = [
        THChatModel(
          userId: currentUserId,
          userName: currentUserName,
          isSend: isSend,
          time: _currentTime.millisecondsSinceEpoch,
          message: "你吃饭了吗？？",
        )
      ];
      yield THChatListState(chatList: list);
    } else if (event is THChatSendMessageEvent) {
      String formUserId = currentUserId;
      String targetId = event.targetId;
      String content = event.content;
      yield* _sendTextMessage(targetId, formUserId, content);
    } else if (event is THChatReceiverMessageEvent) {
      if (state is THChatListState) {
        final List<THChatModel> chatItems =
            List.from((state as THChatListState).chatList)
              ..add(event.chatModel);
        yield THChatListState(chatList: chatItems);
      }
    }
  }

  void _initChat(String userId, String accessToken) {
    _socketChannel = IO.io(
        '${Platform.isIOS ? _SOCKET_IOS_URL : _SOCKET_ANDROID_URL}?userId=$userId&access_token=$accessToken',
        OptionBuilder()
            // for Flutter or Dart VM
            .setTransports(['websocket'])
            // disable auto-connection
            .disableAutoConnect()
            .setExtraHeaders({'access_token': accessToken}) // optional
            .build());

    _socketChannel.connect();

    // 链接建立成功之后，可以发送数据到socket.io的后端了
    _socketChannel.on('connect', (data) {
      print('connect $data');
      EventBusUtil.getInstance()
          .fire(THSocketConnectEvent(status: THSocketConnectType.SUCCESS));
    });

    /**
     * 'connect',
     *  'connect_error',
     *  'connect_timeout',
     *  'connecting',
     *  'disconnect',
     *  'error',
     *  'reconnect',
     *  'reconnect_attempt',
     *  'reconnect_failed',
     *  'reconnect_error',
     *  'reconnecting',
     *  'ping',
     *  'pong'
     */

    // 链接建立失败时调用
    _socketChannel.on('error', (data) => print('error $data'));

    // 链接出错时调用
    _socketChannel.on("connect_error", (data) => print('connect_error: $data'));

    // 链接断开时调用
    _socketChannel.on('disconnect', (data) => print('disconnect $data'));

    // 尝试连接次数
    _socketChannel.on("reconnecting", (data) {
      print('reconnecting $data');
      EventBusUtil.getInstance().fire(THSocketConnectEvent());
      if (data == 3) {
        EventBusUtil.getInstance().fire(
            THSocketConnectEvent(status: THSocketConnectType.RECONNECT_FAILED));
        _socketChannel.disconnect();
      }
    });

    // 连接关闭时调用
    _socketChannel.on('close', (data) => print('close $data'));

    _socketChannel.on("Broadcast", (data) {
      print('Broadcast:: $data');
    });

    // 服务端 emit 一个 SINGLE_CHAT 事件时，可以直接监听到
    _socketChannel.on(ChatConstants.singleChat, (data) {
      EventBusUtil.getInstance().fire(THMessageEvent(message: data));
    });
  }

  Stream<THChatState> _sendTextMessage(
      String targetId, formUserId, String content) async* {
    THMessageTemplate message = THMessageTemplate(
        toUserId: targetId,
        fromUserId: formUserId,
        userId: formUserId,
        content: content,
        type: THMessageType.text);

    print("发送消息:: ${message.toJson()}");
    _socketChannel.emit(ChatConstants.singleChat, message.toJson());

    if (state is THChatListState) {
      THChatModel chatModel = THChatModel(
          userId: currentUserId,
          userName: currentUserName,
          isSend: 1,
          message: content,
          time: _currentTime.millisecondsSinceEpoch);
      final List<THChatModel> chatItems =
          List.from((state as THChatListState).chatList)..add(chatModel);
      yield THChatListState(chatList: chatItems);
    }
  }

  @override
  Future<Function> close() {
    if (null != _socketChannel) {
      _socketChannel.dispose();
    }
    EventBusUtil.getInstance().destroy();
    return super.close();
  }
}
